try:
    import android
except Exception:
    android = None

import re
import htmlentitydefs
import collections
import urllib2
import BeautifulSoup as BS

locations_url = "http://www.macgregorsgrillandtaproom.net/locations.asp"

class Location(object):
    def __init__(self, town, street, cityzip, phone):
        self.town = town
        self.street = street
        self.cityzip = cityzip
        self.search_addr = street + " " + cityzip
        self.phone = phone.split(": ")[-1]
        
        self.specials = []
        
    @property
    def specials_url(self):
        return "http://www.macgregorsgrillandtaproom.net/specials_%s.asp" % self.town
        
    def __repr__(self):
        return "<Location town=%r street=%r cityzip=%r phone=%r>" % (self.town, self.street, self.cityzip, self.phone)
        
    def __unicode__(self):
        beer_specials = u'\n\t'.join(unicode(x) for x in self.beer_specials())
        food_specials = u'\n\t'.join(unicode(x) for x in self.food_specials())
        return u"Town: %s\nStreet Address: %s\nPhone: %s\nFood specials:\n\t%s\nBeer specials:\n\t%s" % (self.town, self.search_addr, self.phone, food_specials, beer_specials)
        
    def food_specials(self):
        return [x for x in self.specials if x.type == "Food"]
    def beer_specials(self):
        return [x for x in self.specials if x.type == "Beer"]
        
class Special(object):
    def __init__(self, type, name, price = None):
        self.type = type
        self.name = name
        self.price = price

    def __repr__(self):
        return "<Special type=%r name=%r price=%r>" % (self.type, self.name, self.price)
        
    def __unicode__(self):
        return u"%s / %s" % (self.name, self.price)

def get_locations():
    soup = BS.BeautifulSoup(urllib2.urlopen(locations_url).read())

    locations = []
    locations_els = soup.findAll("table", attrs={'class':'content'})[-1].findAll("tr")
    for location_el in locations_els:
        img_el = location_el 
        loc_details = [_xml_decode(str(x)).strip() for x in location_el.findAll("td")[1].findAll(text=True)]
        _, town, _, street_addr, cityzip, phone = loc_details[:6]
        
        locations.append(Location(town, street_addr, cityzip, phone))

    return locations

def get_location_from_user(droid, locations):
    droid.dialogCreateAlert("Choose Location")
    by_name = dict((location.town, location) for location in  locations)
    keys = sorted(by_name.keys())
    droid.dialogSetItems(keys)
    droid.dialogShow()
    return by_name[keys[droid.dialogGetResponse().result['item']]]
    
price_re = re.compile(r"(\$?\d+\..*\d\d)")

def get_specials(location):
    url = location.specials_url
    soup = BS.BeautifulSoup(urllib2.urlopen(location.specials_url).read())
    specials = []
    content = soup.find("table", attrs={'class':'content'}).tr.td
    texts = [_xml_decode(str(x)).strip() for x in content.findAll(text=True)]
        
    curtype = None
    curspecial = None
    for text in texts:
        if not text:
            continue
            
        if "pizza menu" in text.lower():
            break
            
        if 'menu' in text.lower():
            continue
        
        if text == "Beer:":
            curtype = "Beer"
            curspecial = None
            continue
        elif text == "Food:":
            curtype = "Food"
            curspecial = None
            continue
            
        if curtype is None:
            continue
        
        if curspecial is None or (curspecial and curspecial.price is not None):
            match = re.search(price_re, text)
            if match is None:
                special = Special(type = curtype, name = text)
                curspecial = special
            else:
                price_text = match.groups(0)[0]
                special = Special(type = curtype, name = text.replace(price_text, '').strip(), price = price_text)
                curspecial = None
            
            specials.append(special)
        
        elif curspecial and curspecial.price is None:
            curspecial.price = text
            curspecial = None
           
    return specials


def main():
    locations = get_locations()
    
    for location in locations:
        location.specials = get_specials(location)
        print unicode(location)
        print '-'*80
        
def main_droid():
    locations = get_locations()
    droid = android.Android()
    location = get_location_from_user(droid, locations)
    location.specials = get_specials(location)
    print unicode(location).encode('utf8')
    
# XML decode

__simplechars_enc = {
                 ord('<') : 'lt',
                 ord('>') : 'gt',
                 #ord("'") : 'apos',
                 ord('"') : 'quot',
                 ord('&') : 'amp',
                 }

__simplechars_dec = dict((v, unichr(k)) for k,v in __simplechars_enc.items())
__simplechars_dec['apos'] = unichr(ord("'"))

def _xml_decode(input, errors='strict'):
    data = collections.deque(input)
    res = []
    append = res.append
    popleft = data.popleft
    extendleft = data.extendleft
    name2codepoint = htmlentitydefs.name2codepoint
    while data:
        ch = popleft()
        if ch == '&':
            curtoken = ''
            is_ref = False
            is_num = False
            is_hex = False
            while len(curtoken) < 10 and data: # so we don't loop to the end of the input
                nch = popleft()

                if nch == '#':
                    is_num = True

                if is_num and len(curtoken) == 1 and nch == 'x':
                    is_hex = True

                if nch == ';':
                    is_ref = True
                    break

                curtoken += nch

                if nch == '&':
                    break

            if not is_ref:
                extendleft(reversed(curtoken)) # put it back
                append('&')      # this should not have been here, but we're nice so we'll put it back
                continue

            else:
                if is_num:
                    try:
                        curtoken = curtoken[1:]  # chop the #
                        if is_hex:
                            curtoken = curtoken[1:] # chop the x
                            och = int(curtoken, 16)
                        else:
                            och = int(curtoken, 10)
                        append(unichr(och))
                    except (UnicodeError, ValueError, TypeError):
                        pass
                    else:
                        continue

                if curtoken in name2codepoint:
                    append(unichr(name2codepoint[curtoken]))
                elif curtoken in __simplechars_dec:
                    append(__simplechars_dec[curtoken])
                else:
                    append('&%s;' % (curtoken))
        else:
            append(ch)

    return u''.join(res)
    
if __name__ == '__main__':
    if android is not None:
        main_droid()
    else:
        main()